package com.example.basic.web.service.report.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.basic.utils.CommonConstant;
import com.example.basic.utils.DateUtils;
import com.example.basic.utils.StringUtils;
import com.example.basic.web.model.remains.RemainsInfo;
import com.example.basic.web.model.warn.DepotWarn;
import com.example.basic.web.request.DepotQueryRequest;
import com.example.basic.web.response.PharmStockResponse;
import com.example.basic.web.response.report.InOutRecordResponse;
import com.example.basic.web.response.report.StockCountResponse;
import com.example.basic.web.response.report.StockSumReportResponse;
import com.example.basic.web.service.common.CommonService;
import com.example.basic.web.service.device.DeviceService;
import com.example.basic.web.service.pharmIn.PharmInRecordService;
import com.example.basic.web.service.pharmStock.PharmStockService;
import com.example.basic.web.service.remains.RemainsInfoService;
import com.example.basic.web.service.report.ReportService;
import com.example.basic.web.service.terminal.TerminalRecordService;
import com.example.basic.web.service.warn.DepotWarnService;
import com.example.basic.web.service.zoneDepot.ZoneDepotService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.example.basic.utils.CheckUtil.notNull;


@Service
public class ReportServiceImpl implements ReportService {

    @Resource
    private CommonService commonService;

    @Resource
    private PharmStockService pharmStockService;
    @Resource
    private PharmInRecordService pharmInRecordService;

    @Resource
    private ZoneDepotService zoneDepotService;

    @Resource
    private HttpServletRequest request;

    @Resource
    private DepotWarnService depotWarnService;

    @Resource
    private DeviceService deviceService;

    @Resource
    private RemainsInfoService remainsInfoService;


    @Resource
    private TerminalRecordService terminalRecordService;


    /**
     * 库存信息查询
     * @param queryPage 分页
     * @param searchParam 模糊搜索(遗体名称，拼音码，五笔码)
     * @param pharmCode 库房编码 0-全部
     * @param zoneCode 分区编码 0-全部
     * @param depotCode 库位编码 0-全部
     * @return
     */
    @Override
    public IPage<StockCountResponse> queryStockInfo(Page<StockCountResponse> queryPage, String searchParam, String pharmCode, String zoneCode, String depotCode) {
        return pharmStockService.queryStockInfo(queryPage,searchParam,pharmCode,zoneCode,depotCode);
    }

    /**
     * 库存信息统计
     *
     * @param searchParam 模糊搜索(遗体名称，拼音码，五笔码)
     * @param pharmCode   仓库编码
     * @param zoneCode    分区编码
     * @param depotCode 库位编码
     * @return
     */
    @Override
    public Map stockCount(String searchParam, String pharmCode, String zoneCode, String depotCode) {

        Map map = pharmStockService.stockCount(searchParam, pharmCode,zoneCode,depotCode);
        if(Integer.parseInt(map.get("freeCount").toString()) > 0){
            BigDecimal freeCount = BigDecimal.valueOf(Integer.parseInt(map.get("freeCount").toString()));
            BigDecimal totalCount = BigDecimal.valueOf(Integer.parseInt(map.get("totalCount").toString()));
            BigDecimal useCount = totalCount.subtract(freeCount);
            BigDecimal divide = useCount.divide(totalCount, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
            map.put("useCount",useCount);
            map.put("usageRate",divide.setScale(2)+"%");
        }else {
            map.put("useCount",Integer.parseInt(map.get("totalCount").toString()));
            map.put("usageRate","100%");
        }
        return map;
    }

    /**
     * 出入库记录查询
     * @param queryPage 分页
     * @param searchParam 模糊搜索(遗体名称，拼音码，五笔码)
     * @param pharmCode 库房编码 0-全部
     * @param zoneCode 分区编码 0-全部
     * @param depotCode 库位编码 0-全部
     * @param beginTime 开始时间
     * @param endTime 结束时间
     * @param type 出入库类型 0-全部
     * @return
     */
    @Override
    public IPage<InOutRecordResponse> queryInOutRecord(Page<InOutRecordResponse> queryPage, String searchParam, String pharmCode, String zoneCode, String depotCode, String beginTime, String endTime, String type) {
        return pharmInRecordService.queryInOutRecord(queryPage,searchParam, pharmCode,zoneCode,depotCode,beginTime,endTime,type);
    }

    /**
     * 出入库记录统计
     *
     * @param searchParam 仓库编码
     * @param pharmCode   仓库编码
     * @param zoneCode    分区编码
     * @param depotCode 库位编码
     * @param beginTime 开始时间
     * @param endTime 结束时间
     * @param type 类型
     * @return
     */
    @Override
    public Map InOutRecordCount(String searchParam, String pharmCode, String zoneCode, String depotCode, String beginTime, String endTime, String type) {
        Map map = pharmInRecordService.InOutRecordCount(searchParam, pharmCode, zoneCode, depotCode, beginTime, endTime, type);

        if("1".equals(type)){
            map.put("outNum",0);
        }
        if("2".equals(type)){
            map.put("inNum",0);
        }

        return map;
    }

    /**
     * 库位信息查询
     * @param queryPage 分页
     * @param depotQueryRequest
     * @return
     */
    @Override
    public IPage<StockCountResponse> queryDepotInfo(Page<StockCountResponse> queryPage, DepotQueryRequest depotQueryRequest) {
        return zoneDepotService.queryDepotInfo(queryPage,depotQueryRequest);
    }

    /**
     * 库位信息统计
     * @param depotQueryRequest
     * @return
     */
    @Override
    public Map depotCount(DepotQueryRequest depotQueryRequest) {
        Map map = zoneDepotService.depotCount(depotQueryRequest);

        //总库位
        int totalCount =  Integer.parseInt(map.get("totalCount").toString());
        int useCount = Integer.parseInt(map.get("useCount").toString());
        int freeCount = totalCount - useCount;

        if("0".equals(depotQueryRequest.getStatus())){
            BigDecimal use = BigDecimal.valueOf(useCount);
            if(totalCount == 0){
                map.put("freeCount", "0(0%)");
                map.put("useCount", "0(0%)");
            }else {
                BigDecimal total = BigDecimal.valueOf(totalCount);
                BigDecimal divide = use.divide(total, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
                map.put("useCount", useCount + "(" + divide.setScale(2) + "%)");
                map.put("freeCount", freeCount + "(" + BigDecimal.valueOf(100).subtract(divide.setScale(2)) + "%)");
            }
        }else if ("1".equals(depotQueryRequest.getStatus())){
            map.put("freeCount", "0(0%)");
            map.put("useCount", useCount + "(100%)");
        }else if("2".equals(depotQueryRequest.getStatus())){
            map.put("useCount", "0(0%)");
            map.put("freeCount", freeCount + "(100%)");
        }
        return map;
    }

    /**
     * 库存汇总报表
     * @param pharmCode 仓库编码
     * @param zoneCode 分区编码
     * @return
     */
    @Override
    public Map stockSumReport(String pharmCode, String zoneCode) {
        //创建头部Map
        List<Map> listMaster = new ArrayList<>();
        //创建最终返回的集合
        Map<String, Object> resultMap = new HashMap<>();
        //创建单使用的master
        Map master = new HashMap();
        //查询动作
        List<StockSumReportResponse> list = zoneDepotService.stockSumReport(pharmCode,zoneCode);
        if (!list.isEmpty()) {
            int totalCount = list.stream().mapToInt(StockSumReportResponse::getTotalCount).sum();
            int useCount = list.stream().mapToInt(StockSumReportResponse::getUseCount).sum();

            master.put("totalCount", totalCount);
            master.put("useCount", useCount);
            master.put("freeCount", list.stream().mapToInt(StockSumReportResponse::getFreeCount).sum());
            master.put("date",commonService.getDataBaseTime());
            master.put("operPerson",request.getAttribute("userName"));

            BigDecimal use = BigDecimal.valueOf(useCount);
            if(totalCount == 0){
                master.put("usageRate", "0%");
            }else {
                BigDecimal total = BigDecimal.valueOf(totalCount);
                BigDecimal divide = use.divide(total, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
                master.put("usageRate", divide.setScale(2)+"%");
            }
            listMaster.add(master);
        }
        resultMap.put("Details", list);
        resultMap.put("Master", listMaster);
        return resultMap;
    }

    /**
     * 库存明细报表
     * @param searchParam 模糊搜索(遗体名称，拼音码，五笔码)
     * @param pharmCode 仓库编码
     * @param zoneCode 分区编码
     * @param depotCode 库位编码
     * @param status 状态 0-全部 1-占用，2-空闲
     * @return
     */
    @Override
    public Map stockDetailReport(String searchParam, String pharmCode, String zoneCode, String depotCode, String status) {

        //创建头部Map
        List<Map> listMaster = new ArrayList<>();
        //创建最终返回的集合
        Map<String, Object> resultMap = new HashMap<>();
        //创建单使用的master
        Map master = new HashMap();
        //查询动作
        IPage<PharmStockResponse> pharmStockResponseIPage = pharmStockService.queryList(new Page<>(0, 0), searchParam, "0", pharmCode, zoneCode, depotCode, status);

        if (!pharmStockResponseIPage.getRecords().isEmpty()) {
            int totalCount = pharmStockResponseIPage.getRecords().size();
            int useCount = 0;
            int freeCount = 0;

            if("0".equals(status)){
                useCount = pharmStockResponseIPage.getRecords().stream().filter(pharmStockResponse -> "占用".equals(pharmStockResponse.getStatusName())).collect(Collectors.toList()).size();
                freeCount = totalCount - useCount;

                BigDecimal use = BigDecimal.valueOf(useCount);

                if(totalCount == 0){
                    master.put("usageRate", "0%");
                }else {
                    BigDecimal total = BigDecimal.valueOf(totalCount);
                    BigDecimal divide = use.divide(total, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
                    master.put("usageRate", divide.setScale(2)+"%");
                }
            }else if ("1".equals(status)){
                useCount = totalCount;
                master.put("usageRate","100%");
            }else if("2".equals(status)){
                freeCount = totalCount;
                master.put("usageRate","0%");
            }


            master.put("totalCount", totalCount);
            master.put("useCount", useCount);
            master.put("freeCount", freeCount);
            master.put("date",commonService.getDataBaseTime());
            master.put("operPerson",request.getAttribute("userName"));
            if(!"0".equals(pharmCode)){
                master.put("pharmName",pharmStockResponseIPage.getRecords().get(0).getPharmName());
            }
            if(!"0".equals(zoneCode)){
                master.put("zoneName",pharmStockResponseIPage.getRecords().get(0).getZoneName());
            }

            listMaster.add(master);
        }

        resultMap.put("Details", pharmStockResponseIPage.getRecords());
        resultMap.put("Master", listMaster);
        return resultMap;
    }

    /**
     * 出入库记录报表
     * @param searchParam 模糊搜索(遗体名称，拼音码，五笔码)
     * @param pharmCode 库房编码 0-全部
     * @param zoneCode 分区编码 0-全部
     * @param depotCode 库位编码 0-全部
     * @param beginTime 开始时间
     * @param endTime 结束时间
     * @param type 出入库类型 0-全部
     * @return
     */
    @Override
    public Map InOutRecordReport(String searchParam, String pharmCode, String zoneCode, String depotCode, String beginTime, String endTime, String type) {

        //创建头部Map
        List<Map> listMaster = new ArrayList<>();
        //创建最终返回的集合
        Map<String, Object> resultMap = new HashMap<>();
        //创建单使用的master
        Map master = new HashMap();
        //查询动作
        IPage<InOutRecordResponse> inOutRecordResponseIPage = pharmInRecordService.queryInOutRecord(new Page<>(0, 0), searchParam, pharmCode, zoneCode, depotCode, beginTime, endTime, type);

        if (!inOutRecordResponseIPage.getRecords().isEmpty()) {
            master.put("inNum", inOutRecordResponseIPage.getRecords().stream().filter(inOutRecordResponse -> "入库".equals(inOutRecordResponse.getType())).collect(Collectors.toList()).size());
            master.put("outNum", inOutRecordResponseIPage.getRecords().stream().filter(inOutRecordResponse -> "出库".equals(inOutRecordResponse.getType())).collect(Collectors.toList()).size());
            master.put("date",commonService.getDataBaseTime());
            master.put("operPerson",request.getAttribute("userName"));
            if(!"0".equals(pharmCode)){
                master.put("pharmName",inOutRecordResponseIPage.getRecords().get(0).getPharmName());
            }
            if(!"0".equals(zoneCode)){
                master.put("zoneName",inOutRecordResponseIPage.getRecords().get(0).getZoneName());
            }
            listMaster.add(master);
        }

        resultMap.put("Details", inOutRecordResponseIPage.getRecords());
        resultMap.put("Master", listMaster);
        return resultMap;
    }

    /**
     * 库位信息报表
     * @param depotQueryRequest
     * @return
     */
    @Override
    public Map depotInfoReport(DepotQueryRequest depotQueryRequest) {

        //创建头部Map
        List<Map> listMaster = new ArrayList<>();
        //创建最终返回的集合
        Map<String, Object> resultMap = new HashMap<>();
        //创建单使用的master
        Map master = new HashMap();
        //查询动作
        IPage<StockCountResponse> stockCountResponseIPage = zoneDepotService.queryDepotInfo(new Page<>(0, 0), depotQueryRequest);

        if (!stockCountResponseIPage.getRecords().isEmpty()) {

            int totalCount = stockCountResponseIPage.getRecords().size();
            int useCount = 0;
            int freeCount = 0;

            if("0".equals(depotQueryRequest.getStatus())){
                useCount = stockCountResponseIPage.getRecords().stream().filter(stockCountResponse -> StringUtils.notEmptyParams(stockCountResponse.getRemainsCode())).collect(Collectors.toList()).size();
                freeCount = totalCount - useCount;

                BigDecimal use = BigDecimal.valueOf(useCount);
                if(totalCount == 0){
                    master.put("useCount", "0(0%)");
                    master.put("freeCount","0(0%)");
                }else {
                    BigDecimal total = BigDecimal.valueOf(totalCount);
                    BigDecimal divide = use.divide(total, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
                    master.put("useCount", use+"("+divide.setScale(2)+"%)");
                    master.put("freeCount", freeCount+"("+BigDecimal.valueOf(100).subtract(divide).setScale(2)+"%)");
                }
            }else if ("1".equals(depotQueryRequest.getStatus())){
                useCount = totalCount;
                master.put("useCount", useCount+"(100%)");
            }else if("2".equals(depotQueryRequest.getStatus())){
                freeCount = totalCount;
                master.put("totalCount",freeCount+"100%");
            }

            master.put("date",commonService.getDataBaseTime());
            master.put("operPerson",request.getAttribute("userName"));
            if(!"0".equals(depotQueryRequest.getPharmCode())){
                master.put("pharmName",stockCountResponseIPage.getRecords().get(0).getPharmName());
            }
            if(!"0".equals(depotQueryRequest.getZoneCode())){
                master.put("zoneName",stockCountResponseIPage.getRecords().get(0).getZoneName());
            }
            listMaster.add(master);
        }

        resultMap.put("Details", stockCountResponseIPage.getRecords());
        resultMap.put("Master", listMaster);
        return resultMap;
    }

    /**
     * 库存预警报表
     * @param pharmCode 库房编码 0-全部
     * @param zoneCode 分区编码 0-全部
     * @return
     */
    @Override
    public Map depotWarnReport(String pharmCode, String zoneCode) {

        //创建头部Map
        List<Map> listMaster = new ArrayList<>();
        //创建最终返回的集合
        Map<String, Object> resultMap = new HashMap<>();
        //创建单使用的master
        Map master = new HashMap();
        //查询动作
        IPage<DepotWarn> depotWarnIPage = depotWarnService.queryList(new Page<>(0, 0), pharmCode, zoneCode, "0");

        if (!depotWarnIPage.getRecords().isEmpty()) {
            master.put("date",commonService.getDataBaseTime());
            master.put("operPerson",request.getAttribute("userName"));
            listMaster.add(master);
        }

        resultMap.put("Details", depotWarnIPage.getRecords());
        resultMap.put("Master", listMaster);
        return resultMap;
    }

    /**
     * 首页设备情况
     * @return
     */
    @Override
    public List<Map> homeDeviceReport() {
        return deviceService.homeDeviceReport();
    }

    /**
     * 今日数量统计
     * @return
     */
    @Override
    public Map homeRemainsCount() {
        return remainsInfoService.homeRemainsCount();
    }

    /**
     * 库位安全预警数
     * @return
     */
    @Override
    public Integer homeDepotWarn() {
        return depotWarnService.homeDepotWarn();
    }

    /**
     * 特殊环节占比
     * @param isAll 1-今日，2-历史
     * @return
     */
    @Override
    public Map homeSpecialCount(String isAll) {

        //返回结果
        Map map = new HashMap();

        //获取所有数据
        List<RemainsInfo> remainsInfos = remainsInfoService.homeSpecialCount(isAll);
        if(remainsInfos.size() == 0){
            return map;
        }

        //整容数量
        int plastic = remainsInfos.stream().filter(remainsInfo -> remainsInfo.getSpecialHandle().contains("1")).collect(Collectors.toList()).size();
        map.put("plastic",plastic);
        if(plastic == 0){
            map.put("plasticRate","0%");
        }else {
            BigDecimal multiply = BigDecimal.valueOf(plastic).divide(BigDecimal.valueOf(remainsInfos.size()), 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
            map.put("plasticRate",multiply.setScale(2)+"%");
        }
        //消毒数量
        int disinfect = remainsInfos.stream().filter(remainsInfo -> remainsInfo.getSpecialHandle().contains("2")).collect(Collectors.toList()).size();
        map.put("disinfect",disinfect);
        if(plastic == 0){
            map.put("disinfectRate","0%");
        }else {
            BigDecimal multiply = BigDecimal.valueOf(disinfect).divide(BigDecimal.valueOf(remainsInfos.size()), 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
            map.put("disinfectRate",multiply.setScale(2)+"%");

        }
        //化妆数量
        int makeUp = remainsInfos.stream().filter(remainsInfo -> remainsInfo.getSpecialHandle().contains("3")).collect(Collectors.toList()).size();
        map.put("makeUp",makeUp);
        if(plastic == 0){
            map.put("makeUpRate","0%");
        }else {
            BigDecimal multiply = BigDecimal.valueOf(makeUp).divide(BigDecimal.valueOf(remainsInfos.size()), 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
            map.put("makeUpRate",multiply.setScale(2)+"%");
        }
        //SPA数量
        int spa = remainsInfos.stream().filter(remainsInfo -> remainsInfo.getSpecialHandle().contains("4")).collect(Collectors.toList()).size();
        map.put("spa",spa);
        if(plastic == 0){
            map.put("spaRate","0%");
        }else {
            BigDecimal multiply = BigDecimal.valueOf(spa).divide(BigDecimal.valueOf(remainsInfos.size()), 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
            map.put("spaRate",multiply.setScale(2)+"%");
        }
        map.put("total",remainsInfos.size());


        return map;
    }

    /**
     * 出入库作业执行情况
     * @return
     */
    @Override
    public List<Map> homeInstructCount() {
        return terminalRecordService.homeInstructCount();
    }

    /**
     * 库位统计对比情况
     * @return
     */
    @Override
    public List<Map> homeDepotCount(String pharmCode) {
        notNull(pharmCode,"仓库编码不能为空");
        return zoneDepotService.homeDepotCount(pharmCode);
    }

    /**
     * 近一周火化，入馆统计
     * @return
     */
    @Override
    public Map homeWeekCount() {
        Date dataBaseTime = commonService.getDataBaseTime();

        Calendar instance = Calendar.getInstance();
        instance.setTime(dataBaseTime);
        instance.add(Calendar.DATE,-6);
        Date beginDate = instance.getTime();

        List<RemainsInfo> remainsInfos = remainsInfoService.homeWeekCount(beginDate,dataBaseTime);

        List<String> dateList = new ArrayList<>();
        List<Integer> inNumList = new ArrayList<>();
        List<Integer> cremationNumList = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            instance = Calendar.getInstance();
            instance.setTime(beginDate);
            instance.add(Calendar.DATE,i);
            Date countDate = instance.getTime();

            String count = DateUtils.format(countDate, CommonConstant.TIME_FORMAT_TEN);
            dateList.add(count);

            //入馆数量
            int inNum = remainsInfos.stream().filter(remainsInfo -> DateUtils.format(remainsInfo.getCreateAt(), CommonConstant.TIME_FORMAT_TEN).equals(count)).collect(Collectors.toList()).size();
            inNumList.add(inNum);
            //火化数量
            int cremationNum = remainsInfos.stream().filter(remainsInfo -> remainsInfo.getCremationTime() != null && DateUtils.format(remainsInfo.getCremationTime(), CommonConstant.TIME_FORMAT_TEN).equals(count)).collect(Collectors.toList()).size();
            cremationNumList.add(cremationNum);
        }
        Map resultMap = new HashMap();
        resultMap.put("date",dateList);
        resultMap.put("inNum",inNumList);
        resultMap.put("cremationNumList",cremationNumList);
        return resultMap;
    }
}
